package com.ld.bisystem.wrapper;

import com.baomidou.mybatisplus.annotation.TableName;
import com.ld.bisystem.util.ReflectionUtil;
import com.ld.bisystem.util.StringUtil;
import com.ld.bisystem.wrapper.anno.JoinField;
import com.ld.bisystem.wrapper.anno.JoinOrder;
import com.ld.bisystem.wrapper.anno.JoinTable;
import com.ld.bisystem.wrapper.condition.DateTypeConstant;
import com.ld.bisystem.wrapper.condition.NumberTypeConstant;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.Date;

/**
 * 线程不安全
 */
public class JoinWrapper<E> extends AbstWrapper<JoinWrapper> {

    private E entity;

    private Class entityClass;

    public JoinWrapper(E entity) {
        this.entity = entity;
        this.entityClass = entity.getClass();
        this.init();
    }

    private void init(){
        this.columnInit();
        this.fromInit();
        this.whereInit();
        this.groupInit();
        this.havingInit();
        this.orderInit();
    }

    private void columnInit() {

        for (Field field : ReflectionUtil.getAllDeclaredFields(entityClass)) {
            JoinField joinField = AnnotationUtils.findAnnotation(field, JoinField.class);
            if (joinField == null) {
                continue;
            }
            String name = joinField.columnName();
            if (StringUtil.isNull(name)) {
                name = StringUtil.javaToColumn(field.getName());
            }
            String as =" as " +field.getName();

                if (joinField.dateFunc() != DateTypeConstant.anon) {
                    String dataStr ="DATE_FORMAT("+name+","+joinField.dateFunc().getFormatType()+")";

                    this.select("", dataStr, as);

                } else if (joinField.numberFunc() != NumberTypeConstant.anon) {
                    this.select(joinField.numberFunc().getValue() + "(", name, ")"+as);
                } else {
                    this.select(  "", name, as);
                }


        }
    }

    private void fromInit() {
        TableName tableName = AnnotationUtils.findAnnotation(entityClass, TableName.class);
        if(tableName != null){
            this.from(tableName.value());
            return;
        }
        JoinTable joinTable = AnnotationUtils.findAnnotation(entityClass, JoinTable.class);
        if(StringUtil.isNotNull(joinTable.left())){
            this.from(joinTable.left());
        }
        if(StringUtil.isNotNull(joinTable.on())){
            this.from(joinTable.on(), joinTable.right());
        }
    }



    private void whereInit() {
        for (Field field : ReflectionUtil.getAllDeclaredFields(entityClass)) {
            JoinField joinField = AnnotationUtils.findAnnotation(field, JoinField.class);
            if (joinField == null || !joinField.group()) {
                continue;
            }
            Object val = ReflectionUtil.invokeGetter(entity, field.getName());
            if (ReflectionUtil.isNotEmpty(val)) {
                String name = joinField.columnName();
                if (StringUtil.isNull(name)) {
                    name = StringUtil.javaToColumn(field.getName());
                }
                if(joinField.dateFunc() != DateTypeConstant.anon){
                    //日期格式化到秒
                    if(val instanceof String){
                        String str = (String)val;
                        Date date =  joinField.dateFunc().parseDate(str);
                        val = DateTypeConstant.anon.fomatDate(date);
                    }

                }
                where(name, joinField.value(), val, joinField.and());
            }
        }
    }

    private void groupInit() {
        for (Field field : ReflectionUtil.getAllDeclaredFields(entityClass)) {
            JoinField joinField = AnnotationUtils.findAnnotation(field, JoinField.class);
            if (joinField == null) {
                continue;
            }
            if(joinField.group()){
                String name = joinField.columnName();
                if (StringUtil.isNull(name)) {
                    name = StringUtil.javaToColumn(field.getName());
                }
                group(name);
            }
        }
    }

    private void havingInit() {
        for (Field field : ReflectionUtil.getAllDeclaredFields(entityClass)) {
            JoinField joinField = AnnotationUtils.findAnnotation(field, JoinField.class);
            if (joinField == null || joinField.group()) {
                continue;
            }





            if( joinField.numberFunc() == NumberTypeConstant.anon || joinField.dateFunc() == DateTypeConstant.anon){
                String name  = StringUtil.javaToColumn(field.getName());
                Object val = ReflectionUtil.invokeGetter(entity, field.getName());
                having(name,joinField.value(),val,joinField.and());
            }

        }
    }

    private void orderInit(){
        for (Field field : ReflectionUtil.getAllDeclaredFields(entityClass)) {
            JoinOrder joinOrder = AnnotationUtils.findAnnotation(field, JoinOrder.class);
            JoinField joinField = AnnotationUtils.findAnnotation(field, JoinField.class);
            if (joinField == null || joinOrder == null) {
                continue;
            }
            String name=field.getName();
            //数字聚合,使用别名
            if(joinField.numberFunc() != NumberTypeConstant.anon){
                this.order(name,joinOrder.asc());
            }else {
                //判断是否有列名，否则使用别名
                if (StringUtil.isNotNull(joinField.columnName())) {
                    name = joinField.columnName();
                }
                this.order(name,joinOrder.asc());

            }



        }
    }

}